/**   
 * @Title: BusDpCodeGenerator.java
 * @Package cn.edu.sjtu.se.dslab.component.design.generate
 * @Description: TODO(用一句话描述该文件做什么)
 * @author Thinker
 * @date 2013-7-27 上午8:55:53
 * @version V1.0
 */ 
package cn.edu.sjtu.se.dslab.component.design.generate;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;

import cn.edu.sjtu.se.dslab.component.data.AvionicsEquipment;
import cn.edu.sjtu.se.dslab.component.data.DomainEntity;
import cn.edu.sjtu.se.dslab.component.data.util.DataComponentUtil;
import cn.edu.sjtu.se.dslab.component.dp.parse.DesignPatternInstanceBean;
import cn.edu.sjtu.se.dslab.component.dp.parse.Property;
import cn.edu.sjtu.se.dslab.component.method.InterfaceMethod;
import cn.edu.sjtu.se.dslab.project.Project;
import cn.edu.sjtu.se.dslab.service.IAvionicsEquipmentService;
import cn.edu.sjtu.se.dslab.service.IDataComponentService;
import cn.edu.sjtu.se.dslab.service.IDomainEntityService;
import cn.edu.sjtu.se.dslab.service.IInterfaceMethodService;
import cn.edu.sjtu.se.dslab.util.FileUtil;

/** 
 * @ClassName: BusDpCodeGenerator
 * @Description: 生成总线设计模式代码
 * @author longshaohang
 * @date 2013-7-27 上午8:55:53
 * 
 */
@Service("busDpCodeGenerator")
public class BusDpCodeGenerator extends DesignPatternCodeGenerator{

	//define template file
	private static final String SHARED_MEMORY_TEMPLATE_NAME = "shared_memory_area.vm";
	private static final String READ_WRITE_PROXY_TEMPLATE_NAME = "read_write_proxy.vm";
	//define target file
	private static final String SHARED_MEMORY_FILE_NAME = "shared_memory_area.h";
	private static final String READ_WRITE_PROXY_FILE_NAME = "proxy.c";
	private static final String DATA_ENTITY_FILE_NAME = "data_entity.h";

	@Resource(name = "dataComponentService")
	IDataComponentService dataComponentService;

	@Resource(name = "domainEntityService")
	IDomainEntityService domainEntityService;
	
	@Resource(name="avionicsEquipmentService")
	IAvionicsEquipmentService avionicsEquipmentService;

	@Resource(name="dataComponentUtil")
	DataComponentUtil dataComponentUtil;
	
	@Resource(name="interfaceMethodService")
	IInterfaceMethodService interfaceMethodService;

	public BusDpCodeGenerator(){
		super();
	}

	/** (非 Javadoc) 
	 * Title: generateCode
	 * Description:
	 * @param dpiBean
	 * @return
	 * @throws IOException
	 * @see cn.edu.sjtu.se.dslab.component.design.generate.DesignPatternCodeGenerator#generateCode(cn.edu.sjtu.se.dslab.component.design.parse.DesignPatternInstanceBean)
	 */
	@Override
	public void generateCode(String targetDirPath,Project project,  DesignPatternInstanceBean ...dpiBean)
			throws IOException {
		String absoluteTargetDirPath = FileUtil.getRootPath() + targetDirPath;
		
		Map<String, String> sharedMemoryArea = new HashMap<String, String>();
		Set<Long> dataEntityIdSet = new HashSet<Long>(); 
		
		List<Map<String, Property>> instances = dpiBean[0].getInstances();
		for (Map<String, Property> instance: instances){
			String equipmentName = "";
			String equipmentNumber = "";
			//equipment
			Property equipmentProperty = instance.get("equipment");
			AvionicsEquipment equipment = avionicsEquipmentService.getAvionicsEquipmentByUri(equipmentProperty.getValue());
			equipmentName = equipment.getName();
			inputData("equipment",equipmentName.toLowerCase());
			
			//bus_type
			//Property busTypeProperty = instance.get("bus_type");
			
			//bus_data_area
			Property busDataAreaProperty = instance.get("bus_data_area");
			inputData("bus_data_area", busDataAreaProperty.getValue());
			
			//entity_data_area
			Property entityDataAreaProperty = instance.get("entity_data_area");
			String[] uris = entityDataAreaProperty.getValue().split("/");
			List<Long> domainEntityIdList = new ArrayList<Long>();
			List<String> dependFileList = new ArrayList<String>();
			List<String> domainEntityList = new ArrayList<String>();
			for (String uri: uris){
				DomainEntity domainEntity = domainEntityService.getDomainEntityByUri(uri);
				domainEntityIdList.add( domainEntity.getId());
				domainEntityList.add(domainEntity.getName());
				if (!dataEntityIdSet.contains( domainEntity.getId())){
					dataEntityIdSet.add(domainEntity.getId());
				}
			}
			inputData("entity_data_area", domainEntityList);
			//去掉文件的路径，只剩下文件名
			for(String s: dataComponentUtil.getDependences(domainEntityIdList)){
				String tmp = s.substring(s.lastIndexOf('/')+1,	s.length());
				dependFileList.add(tmp);
				FileUtil.copyFile(s, absoluteTargetDirPath, null);// 把依赖的文件复制到生成代码的文件夹下
			}
			inputData("depend_files", dependFileList);
			
			//equipment_number
//			sharedMemoryArea.add(p.getValue());
			Property equipmentNumberProperty = instance.get("equipment_number");
			equipmentNumber = equipmentNumberProperty.getValue();
					
			//read_bus_processing_method
			Property readBusProperty = instance.get("read_bus_processing_method");
			InterfaceMethod method = interfaceMethodService.getInterfaceMethodById(
						new Long(readBusProperty.getValue()));
			//inputData("read_bus_processing_method", method.getMethodSigniture());
			inputData("read_bus_processing_method", method.getName());
			//read frequency
			Property readFrequencyProperty = instance.get("read_frequency");
			inputData("read_frequency", readFrequencyProperty.getValue());
			//write_bus_processing_method
			Property writeBusProperty = instance.get("write_bus_processing_method");
			InterfaceMethod writeMethod = interfaceMethodService.getInterfaceMethodById(
						new Long(writeBusProperty.getValue()));
			inputData("write_bus_processing_method", writeMethod.getName());
			//write_frequency
			Property writeFrequencyProperty = instance.get("write_frequency");
			inputData("write_frequency", writeFrequencyProperty.getValue());
			
			sharedMemoryArea.put(equipmentName, equipmentNumber);
			//generate proxy files
//			StringBuffer rwpFile = new StringBuffer(absoluteTargetDirPath);
			StringBuffer rwpFile = new StringBuffer(targetDirPath);
			rwpFile.append(equipmentName).append("_").append(READ_WRITE_PROXY_FILE_NAME);
			generateCodeFile(rwpFile.toString(), READ_WRITE_PROXY_TEMPLATE_NAME);
			
			//generate data_entity definition file
			StringBuffer variableFile = new StringBuffer(absoluteTargetDirPath);
			variableFile.append(DATA_ENTITY_FILE_NAME);
			dataComponentUtil.generateBusData(new ArrayList<Long>(dataEntityIdSet), variableFile.toString());
		}
		
//		StringBuffer rwpFile = new StringBuffer(absoluteTargetDirPath);
		StringBuffer rwpFile = new StringBuffer(targetDirPath);
		rwpFile.append("/").append(SHARED_MEMORY_FILE_NAME);
		inputData("file_name", SHARED_MEMORY_FILE_NAME.replace('.', '_').toUpperCase());
		inputData("equipment_numbers", sharedMemoryArea.entrySet());
		generateCodeFile(rwpFile.toString(), SHARED_MEMORY_TEMPLATE_NAME);
	}

}
